unsigned long long value(const char * word);
unsigned int len(const char * string);
void reset_flags(int flags[], int special);
void update_flags(int flags[], int i);
int check_flags(int flags[]);

void generate_password(char password[], const char * keyword, const char * service, const char * username, int length, int special)
{
	char * charactors =	"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*";

	unsigned long long seed = value(keyword) + value(service) + value(username) + length + special;

	int  keyword_length = len( keyword);
	int  service_length = len( service);
	int username_length = len(username);

	int flags[4] = {0,0,0,0}; // lower, upper, numbers, specials
	int range = 62 + (8 * special);
	int attempt = 0;
	while ( check_flags(flags) && attempt < 100)
	{
		attempt++;
		reset_flags(flags, special);
		// generate password
		for ( int i = 0; i < length; i++ )
		{
			// Updates seed
			seed += 1 + keyword[i % keyword_length] + service[i % service_length] + username[i % username_length] + length + special;
			
			update_flags(flags, seed % range);
			password[i] = charactors[seed % range];
		}
		password[length] = '\0';
	}
}

unsigned long long value(const char * word)
{
	unsigned long long value = 0;
	for ( ;*word != '\0'; word++ )
	{
		value += *word;
	}
	return value;
}

unsigned int len(const char * string)
{
	const char * end = string;
	while (*end != 0) 
	{	
		end++; 
	}
	return end - string;
}

void reset_flags(int flags[], int special)
{
	flags[0] = 0;
	flags[1] = 0;
	flags[2] = 0;
	flags[3] = !special;
	return;
}

void update_flags(int flags[], int i) {

	if      ( i < 26 ) {
		flags[0]++;	   }

	else if ( i < 52 ) {
		flags[1]++;	   }

	else if ( i < 62 ) {
		flags[2]++;    }

	else               {
		flags[3]++;	   }
	return;
                                      }

int check_flags(int flags[])
{
	return ( flags[0] < 1 || flags[1] < 1 || flags[2] < 1 || flags[3] < 1 );
}
